/**
 * JSparrow - Une version numérique du jeu "Attention Pirates !" - Copyright (C) 2014 Black Pearl
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If
 * not, see <http://www.gnu.org/licenses/>.
 */
package App.Modele;

import App.main;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;

/**
 * Classe de gestion de partie.
 *
 * @author BlackPearl
 */
public class Partie implements Serializable {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private final String nom;
    private final int nbJoueurs;
    private Date dateEnregistrement;
    private String historique;
    private Plateau plateau;
    private ArrayList<Joueur> joueurs;
    private Joueur joueurActuel;
    private int actionEnCours;

    /**
     * Initalisation du contexte.
     *
     * @param nom nom de la partie
     * @param nbJoueurs nombre de joueurs de la partie
     */
    public Partie(String nom, int nbJoueurs) {
        if (main.DEBUG_MODE) {
            System.out.println("Partie [" + nom + "] == Creation d'une partie");
        }
        this.nom = nom;
        this.nbJoueurs = nbJoueurs;
        this.joueurs = new ArrayList<Joueur>();
        this.actionEnCours = 0;
    }

    public int getActionEnCours() {
		return actionEnCours;
	}
    
    public void incActionEnCours()
    {
    	if(actionEnCours==1)
    	{
    		this.joueurActuel.incNumTour();
    		this.joueurActuel = this.joueurs.get((this.joueurActuel.getID()+1) % this.nbJoueurs);
    	}
    	actionEnCours = (actionEnCours + 1)%2;
    }
    
    public boolean configurationEnCours()
    {
    	if(this.joueurActuel.getNumTour() == 0 && this.actionEnCours == 0)
    		return true;
    	else
    		return false;
    }

	/**
     * Ajouter un joueur dans la partie.
     *
     * @param nom Nom du joueur
     * @return true si le joueur a été ajouté, false sinon
     */
    public boolean ajouterJoueur(String nom) {
        if (main.DEBUG_MODE) {
            System.out.println("Partie [" + nom + "] == Ajout du joueur " + nom);
        }
        if (this.joueurs.size() < this.nbJoueurs) {
            this.joueurs.add(new Joueur(nom));
            return true;
        }
        return false;
    }

    /**
     * Initialiser la partie.
     */
    public void initialiser() {
        if (main.DEBUG_MODE) {
            System.out.println("Partie [" + this.nom + "] == Initialisation de la partie");
        }
        if (this.joueurs.size() == this.nbJoueurs) {
            this.joueurActuel = this.joueurs.get(0);
            ArrayList<Bateau> listeBateaux = new ArrayList<Bateau>();
            for (Joueur j : this.joueurs) {
                listeBateaux.add(j.getBateau());
            }
            this.plateau = new Plateau(listeBateaux);
        } else {
            if (main.DEBUG_MODE) {
                System.out.println("Partie [" + this.nom + "] == Nombre de joueurs incorrect");
            }
        }
    }

    /**
     * Obtenir le plateau de jeu.
     *
     * @return le plateau
     */
    public Plateau getPlateau() {
        return this.plateau;
    }

    /**
     * Obtenir un joueur.
     *
     * @return le joueur actuel
     */
    public Joueur getJoueur() {
        return this.joueurActuel;
    }

    /**
     * Obtenir un joueur.
     *
     * Attention une liste commence à 0.
     *
     * @param numeroJoueur le numéro du joueur
     * @return le joueur dont le numero est donné en paramètre ou null s'il n'existe pas
     */
    public Joueur getJoueur(int numeroJoueur) {
        if (this.joueurs.size() > numeroJoueur && numeroJoueur >= 0) {
            return this.joueurs.get(numeroJoueur);
        }
        return null;
    }

    /**
     * Obtenir la liste des joueurs.
     *
     * @return le tableau des joueurs
     */
    public ArrayList<Joueur> getJoueurs() {
        return this.joueurs;
    }

    /**
     * Obtenir le nombre de joueurs.
     *
     * @return le nombre de joueurs
     */
    public int getNbJoueurs() {
        return this.nbJoueurs;
    }

    /**
     * Vérifier si la partie est terminée, et, le cas échéant, donner le nom du gagnant.
     *
     * @return le nom du gagnant ou null si la partie continue
     */
    public String verificationFinPartie() {
        String gagnant = null;
        Boolean repairesVides = true;
        // On vérifie que tous les repaires sont vides
        for (Repaire r : this.plateau.getListeRepaires()) {
            if (r.getNbTresors() > 0) {
                repairesVides = false;
            }
        }
        // Si oui, la partie est terminée et il faut compter le nombre de trésors pour chaque joueur
        if (repairesVides) {
            int scoreGagnant = 0;
            int scoreCourant;
            for (Joueur j : this.joueurs) {
                scoreCourant = j.getScore() + j.getBateau().getNbTresors();
                if (scoreCourant > scoreGagnant) {
                    scoreGagnant = scoreCourant;
                    gagnant = j.getNom();
                }
            }
        } else {
            // Si tous les trésors n'ont pas été pris 
            switch (this.nbJoueurs) {
                case 2:
                    // Pour 2 joueurs, le score gagnant est de 16
                    for (Joueur j : this.joueurs) {
                        if (j.getScore() >= 16) {
                            gagnant = j.getNom();
                        }
                    }
                    break;
                case 3:
                    // Pour 3 joueurs, le score gagnant est de 13
                    for (Joueur j : this.joueurs) {
                        if (j.getScore() >= 13) {
                            gagnant = j.getNom();
                        }
                    }
                    break;
                case 4:
                    // Pour 4 joueurs, le score gagnant est de 11
                    for (Joueur j : this.joueurs) {
                        if (j.getScore() >= 11) {
                            gagnant = j.getNom();
                        }
                    }
                    break;
                case 5:
                    // Pour 5 joueurs, le score gagnant est de 10
                    for (Joueur j : this.joueurs) {
                        if (j.getScore() >= 10) {
                            gagnant = j.getNom();
                        }
                    }
                    break;
                case 6:
                    // Pour 6 joueurs, le score gagnant est de 9
                    for (Joueur j : this.joueurs) {
                        if (j.getScore() >= 9) {
                            gagnant = j.getNom();
                        }
                    }
                    break;
                default:
                    gagnant = null;
                    break;
            }
        }
        if (main.DEBUG_MODE) {
            if (gagnant == null) {
                System.out.println("Partie [" + this.nom + "] == Pas de gagnant");
            } else {
                System.out.println("Partie [" + this.nom + "] == Vainqueur [" + gagnant + "]");
            }
        }
        return gagnant;
    }

    /**
     * Obtenir le nom de la partie.
     *
     * @return le nom de la partie
     */
    public String getNom() {
        return nom;
    }

	public Date getDateEnregistrement() {
		return dateEnregistrement;
	}

	public void setDateEnregistrement(Date dateEnregistrement) {
		this.dateEnregistrement = dateEnregistrement;
	}

	public String toCom() {
		StringBuilder partieStringBuffer = new StringBuilder();
        ArrayList<Joueur> hash = new ArrayList<Joueur>();
        ArrayList<Joueur> hashTmp = new ArrayList<Joueur>(joueurs);
        hashTmp.remove(this.joueurActuel);
        hash.add(joueurActuel);
        hash.addAll(hashTmp);
        int cpt = 0;
        for (Joueur j : hash) {
            cpt++;
            partieStringBuffer.append(j.getNom());
            partieStringBuffer.append("-");
            partieStringBuffer.append(j.getScore());
            partieStringBuffer.append("-");
            partieStringBuffer.append(j.getBateau().getNbTresors());
            if(cpt < hash.size()){
            	partieStringBuffer.append("_");
            }
        }
        return partieStringBuffer.toString();
	}

}
